iconhelper: Add support for GskTexture
authorBenjamin Otte <otte@redhat.com>
Mon, 7 Nov 2016 17:25:12 +0000 (18:25 +0100)
committerBenjamin Otte <otte@redhat.com>
Tue, 8 Nov 2016 19:31:34 +0000 (20:31 +0100)
... and use that in GtkImage.

gtk/gtkiconhelper.c
gtk/gtkiconhelperprivate.h
gtk/gtkimage.c

index 1d196d4c925822921829f3bac3579874d0ce0c66..278ace34ffd3b8416ff151027232af08049c8932 100644 (file)
@@ -43,6 +43,7 @@ struct _GtkIconHelperPrivate {
   guint rendered_surface_is_symbolic : 1;
 
   cairo_surface_t *rendered_surface;
+  GskTexture *texture;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkIconHelper, gtk_icon_helper, GTK_TYPE_CSS_GADGET)
@@ -50,6 +51,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (GtkIconHelper, gtk_icon_helper, GTK_TYPE_CSS_GADGET)
 static void
 gtk_icon_helper_invalidate (GtkIconHelper *self)
 {
+  g_clear_pointer (&self->priv->texture, gsk_texture_unref);
+
   if (self->priv->rendered_surface != NULL)
     {
       cairo_surface_destroy (self->priv->rendered_surface);
@@ -95,6 +98,7 @@ gtk_icon_helper_take_definition (GtkIconHelper      *self,
 void
 _gtk_icon_helper_clear (GtkIconHelper *self)
 {
+  g_clear_pointer (&self->priv->texture, gsk_texture_unref);
   g_clear_pointer (&self->priv->rendered_surface, cairo_surface_destroy);
 
   gtk_image_definition_unref (self->priv->def);
@@ -554,6 +558,34 @@ gtk_icon_helper_ensure_surface (GtkIconHelper *self)
   self->priv->rendered_surface = gtk_icon_helper_load_surface (self, scale);
 }
 
+static void
+gtk_icon_helper_ensure_texture (GtkIconHelper *self,
+                                GskRenderer   *renderer)
+{
+  cairo_surface_t *map;
+  int width, height, scale;
+
+  if (self->priv->texture)
+    return;
+
+  gtk_icon_helper_ensure_surface (self);
+  if (self->priv->rendered_surface == NULL)
+    return;
+
+  scale = gtk_widget_get_scale_factor (gtk_css_gadget_get_owner (GTK_CSS_GADGET (self))),
+  _gtk_icon_helper_get_size (self, &width, &height);
+  map = cairo_surface_map_to_image (self->priv->rendered_surface,
+                                    &(GdkRectangle) { 0, 0, width * scale, height * scale});
+
+  self->priv->texture = gsk_texture_new_for_data (renderer,
+                                                  cairo_image_surface_get_data (map),
+                                                  width * scale,
+                                                  height * scale,
+                                                  cairo_image_surface_get_stride (map));
+
+  cairo_surface_unmap_image (self->priv->rendered_surface, map);
+}
+
 void
 _gtk_icon_helper_get_size (GtkIconHelper *self,
                            gint *width_out,
@@ -825,6 +857,29 @@ _gtk_icon_helper_draw (GtkIconHelper *self,
     }
 }
 
+GskRenderNode *
+gtk_icon_helper_get_render_node (GtkIconHelper *self,
+                                 GskRenderer   *renderer)
+{
+  GskTexture *texture;
+  GskRenderNode *node;
+  graphene_rect_t bounds;
+
+  gtk_icon_helper_ensure_texture (self, renderer);
+  texture = self->priv->texture;
+  if (texture == NULL)
+    return NULL;
+  graphene_rect_init (&bounds, 0, 0, gsk_texture_get_width (texture), gsk_texture_get_height (texture));
+
+  node = gsk_renderer_create_render_node (renderer);
+  gsk_render_node_set_name (node, "Icon Helper");
+  gsk_render_node_set_bounds (node, &bounds);
+  gsk_render_node_set_texture (node, texture);
+
+  return node;
+}
+
 gboolean
 _gtk_icon_helper_get_is_empty (GtkIconHelper *self)
 {
index 849aeb12a6d38bbb60ab6893dca9acce22a937fa..6576e81519aaddb75349113372f89a66b56b1ac3 100644 (file)
@@ -125,6 +125,8 @@ void _gtk_icon_helper_draw (GtkIconHelper *self,
                             cairo_t *cr,
                             gdouble x,
                             gdouble y);
+GskRenderNode * gtk_icon_helper_get_render_node (GtkIconHelper *self,
+                                                 GskRenderer   *renderer);
 
 gboolean _gtk_icon_helper_get_force_scale_pixbuf (GtkIconHelper *self);
 void     _gtk_icon_helper_set_force_scale_pixbuf (GtkIconHelper *self,
index ae8dec8c5efaf04bddcd96f897d6947591cd9e29..7d5e99f92fd889bacf51f3ee0d03e01eab20f57e 100644 (file)
@@ -1420,44 +1420,44 @@ gtk_image_get_render_node (GtkWidget   *widget,
   if (res == NULL)
     return NULL;
 
-  node = gtk_widget_create_render_node (widget, renderer, "Image Content");
+  if (gtk_image_get_storage_type (image) == GTK_IMAGE_ANIMATION)
+    {
+      node = gtk_widget_create_render_node (widget, renderer, "Image Content");
 
-  gtk_widget_get_clip (widget, &clip);
-  _gtk_widget_get_allocation (widget, &alloc);
+      gtk_widget_get_clip (widget, &clip);
+      _gtk_widget_get_allocation (widget, &alloc);
 
-  cr = gsk_render_node_get_draw_context (node, renderer);
-  cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y);
-  x = 0;
-  y = 0;
-  width = alloc.width;
-  height = alloc.height;
+      cr = gsk_render_node_get_draw_context (node, renderer);
+      cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y);
+      x = 0;
+      y = 0;
+      width = alloc.width;
+      height = alloc.height;
 
-  _gtk_icon_helper_get_size (priv->icon_helper, &w, &h);
+      _gtk_icon_helper_get_size (priv->icon_helper, &w, &h);
 
-  baseline = gtk_widget_get_allocated_baseline (widget);
+      baseline = gtk_widget_get_allocated_baseline (widget);
 
-  if (baseline == -1)
-    y += floor(height - h) / 2;
-  else
-    y += CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h);
+      if (baseline == -1)
+        y += floor(height - h) / 2;
+      else
+        y += CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h);
 
-  x += (width - w) / 2;
+      x += (width - w) / 2;
 
-  if (gtk_image_get_storage_type (image) == GTK_IMAGE_ANIMATION)
-    {
       GtkStyleContext *context = gtk_widget_get_style_context (widget);
       GdkPixbuf *pixbuf = get_animation_frame (image);
 
       gtk_render_icon (context, cr, pixbuf, x, y);
       g_object_unref (pixbuf);
+
+      cairo_destroy (cr);
     }
   else
     {
-      _gtk_icon_helper_draw (priv->icon_helper, cr, x, y);
+      node = gtk_icon_helper_get_render_node (priv->icon_helper, renderer);
     }
 
-  cairo_destroy (cr);
-
   gsk_render_node_append_child (res, node);
   gsk_render_node_unref (node);